/*
 * Copyright (c) 2024 iSOFT INFRASTRUCTURE SOFTWARE CO., LTD.
 * easyAda is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */

#include <arch/context.h>
#include <arch/regs.h>
#include <stdlib/string.h>
#include <core/dprintf.h>
#include <core/schedule.h>
#include <core/task.h>

void context_init(context_t *context, int type)
{
    memset(context, 0, sizeof(context_t));
}
void context_set_stack(context_t *context, void *stack, uint32_t stack_size)
{
    context->sp_el0 = (uint64_t)stack + stack_size;
}
void context_set_ipcbuffer(context_t *context, void *ipcbuffer)
{
}
void context_set_retcode(context_t *context, uint64_t retcode)
{
    context->regs[X0] = retcode;
}
void context_set_reg_param(context_t *context, uint64_t p0, uint64_t p1, uint64_t p2, uint64_t p3, uint64_t p4,
                           uint64_t p5, uint64_t p6, uint64_t p7)
{
    context->regs[X0] = p0;
    context->regs[X1] = p1;
    context->regs[X2] = p2;
    context->regs[X3] = p3;
    context->regs[X4] = p4;
    context->regs[X5] = p5;
    context->regs[X6] = p6;
    context->regs[X7] = p7;
}

void context_set_entry(context_t *context, uint64_t entry)
{
    context->elr = entry;
}
void context_restore_current(void)
{
    asm volatile("msr TPIDRRO_EL0, %0" ::"r"(current()->ipcbuffer));
    uint64_t *restore_sp = current_context_nill();
    asm volatile("mov sp, %0\n\t"
                 "ldp	x0, x2, [sp],#16\n\t"
                 "msr    spsr_el1, x0\n\t"
                 "msr    sp_el0,x2\n\t"
                 "ldp	x2, x0, [sp],#16	\n\t"
                 "msr	elr_el1, x2 \n\t"
                 "ldp	x1, x2, [sp],#16\n\t"
                 "ldp	x3, x4, [sp],#16\n\t"
                 "ldp	x5, x6, [sp],#16\n\t"
                 "ldp	x7, x8, [sp],#16\n\t"
                 "ldp	x9, x10, [sp],#16\n\t"
                 "ldp	x11, x12, [sp],#16\n\t"
                 "ldp	x13, x14, [sp],#16\n\t"
                 "ldp	x15, x16, [sp],#16\n\t"
                 "ldp	x17, x18, [sp],#16\n\t"
                 "ldp	x19, x20, [sp],#16\n\t"
                 "ldp	x21, x22, [sp],#16\n\t"
                 "ldp	x23, x24, [sp],#16\n\t"
                 "ldp	x25, x26, [sp],#16\n\t"
                 "ldp	x27, x28, [sp],#16\n\t"
                 "ldp	x29, x30, [sp],#16\n\t"
                 "eret   \n\t"
                 :
                 : "r"(restore_sp)
                 : "memory");
}

uint64_t *current_context_sp(void)
{
    return &task_get_context(current())->regs[X30];
}
uint64_t *current_context_elr(void)
{
    return &task_get_context(current())->elr;
}
uint64_t *current_context_nill(void)
{
    return &task_get_context(current())->spsr;
}
